unit GridHandler;

interface

uses  Winapi.Windows, Winapi.Messages, System.SysUtils, StrUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.DBCtrls, Vcl.Grids, Vcl.DBGrids,
  Data.DB, Data.Win.ADODB, Vcl.Mask;

procedure FixDBGridColumnsWidth(const DBGrid: TDBGrid);
procedure DBGridMouseMove(const Grid: TDBGrid; Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure DBGridTitleClick(const Grid: TDBGrid; Column: TColumn);
procedure DBGridDrawRows(
   Sender: TObject;
   const Rect: TRect;
   DataCol: Integer;
   Column: TColumn;
   State: TGridDrawState) ;
procedure DBResDrawRows(
   Sender: TObject;
   const Rect: TRect;
   DataCol: Integer;
   Column: TColumn;
   State: TGridDrawState) ;

implementation

(*******************************************************************************
  ResizeGridCols():  Stretches the dynamic column so that the grid is always
                     filled with columns (no dead space). other cols keep
                     their standard width.
*******************************************************************************)
procedure FixDBGridColumnsWidth(const DBGrid: TDBGrid);
var
  i : integer;
  TotWidth : integer;
  VarWidth : integer;
  ResizableColumnCount : integer;
  AColumn : TColumn;
begin
  //total width of all columns before resize
  TotWidth := 0;
  //how to divide any extra space in the grid
  VarWidth := 0;
  //how many columns need to be auto-resized
  ResizableColumnCount := 0;

  for i := 0 to -1 + DBGrid.Columns.Count do
  begin
    TotWidth := TotWidth + DBGrid.Columns[i].Width;
    if DBGrid.Columns[i].Field.Tag <> 0 then
      Inc(ResizableColumnCount);
  end;

  //add 1px for the column separator line
  if dgColLines in DBGrid.Options then
    TotWidth := TotWidth + DBGrid.Columns.Count;

  //add indicator column width
  if dgIndicator in DBGrid.Options then
    TotWidth := TotWidth + IndicatorWidth;

  //width vale "left"
  VarWidth :=  DBGrid.ClientWidth - TotWidth;

  //Equally distribute VarWidth
  //to all auto-resizable columns
  if ResizableColumnCount > 0 then
    VarWidth := varWidth div ResizableColumnCount;

  for i := 0 to -1 + DBGrid.Columns.Count do
  begin
    AColumn := DBGrid.Columns[i];
    if AColumn.Field.Tag <> 0 then
    begin
      AColumn.Width := AColumn.Width + VarWidth;
      if AColumn.Width < AColumn.Field.Tag then
        AColumn.Width := AColumn.Field.Tag;
    end;
  end;
end; (*FixDBGridColumnsWidth*)

(*******************************************************************************
  DBGridMouseMove():  Change the cursor to a hand when over the top row of the
                      grid to signify to the user that clicking the top row will
                      cause the DB to sort on that Field.
*******************************************************************************)
procedure DBGridMouseMove(const Grid: TDBGrid; Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  pt: TGridcoord;
begin
  pt:= Grid.MouseCoord(x, y);

  if pt.y=0 then
    Grid.Cursor:=crHandPoint
  else
    Grid.Cursor:=crDefault;
end;
(*******************************************************************************
  DBGridTitleClick():  Changes the title font to bold if a title is configured
                       to be the sort title. Also, causes the table to sort based
                       on the selected sort column.
*******************************************************************************)
procedure DBGridTitleClick(const Grid: TDBGrid; Column: TColumn);
{$J+}
 const PreviousColumnIndex : integer = -1;
{$J-}
begin
  if Grid.DataSource.DataSet is TCustomADODataSet then
  with TCustomADODataSet(Grid.DataSource.DataSet) do
  begin
    try
      Grid.Columns[PreviousColumnIndex].title.Font.Style :=
      Grid.Columns[PreviousColumnIndex].title.Font.Style - [fsBold];
    except
      //leave blank- should only be needed to handle initial call to function.
    end;
    Column.title.Font.Style := Column.title.Font.Style + [fsBold];
    PreviousColumnIndex := Column.Index;

    if (PosEx(Column.Field.FieldName, Sort,1) = 1) and (PosEx(' DESC', Sort,1)= 0) then
      Sort := Column.Field.FieldName + ' DESC'
    else
      Sort := Column.Field.FieldName + ' ASC';
  end;
end;
(*******************************************************************************
  DBGridDrawRows():  This procedure draws the grid rows in alternating
                           colors to help increase readability.
*******************************************************************************)
procedure DBGridDrawRows(
   Sender: TObject;
   const Rect: TRect;
   DataCol: Integer;
   Column: TColumn;
   State: TGridDrawState) ;
 var
   grid : TDBGrid;
   row : integer;
   tmpDate: TDateTime;
 begin
   grid := sender as TDBGrid;
   tmpDate := Now;
   row := grid.DataSource.DataSet.RecNo;
   // START MOD
   if (grid.DataSource.DataSet.FieldByName('STATUS').AsString <> 'COMPLETE')and
      (grid.DataSource.DataSet.FieldByName('DESCRIPTION').AsString <> '') and
      (grid.DataSource.DataSet.FieldByName('DUE_DATE').AsDateTime < Now) then
          grid.Canvas.Brush.Color := clRed
          else
            if (grid.DataSource.DataSet.FieldByName('STATUS').AsString <> 'COMPLETE')and
               (grid.DataSource.DataSet.FieldByName('DESCRIPTION').AsString <> '') and
               (grid.DataSource.DataSet.FieldByName('DUE_DATE').AsDateTime - tmpDate <= 7) then
              grid.Canvas.Brush.Color := clYellow
        else
          begin
             if Odd(row) then
               grid.Canvas.Brush.Color := clSilver
             else
               grid.Canvas.Brush.Color := clWhite;
          end;

   grid.DefaultDrawColumnCell(Rect, DataCol, Column, State) ;
  end; (* DBGrid OnDrawColumnCell *)

 (*******************************************************************************
  DBResDrawRows():  This procedure draws the grid rows in alternating
                    colors to help increase readability- exclusive to Resources
                    Table.
*******************************************************************************)
procedure DBResDrawRows(
   Sender: TObject;
   const Rect: TRect;
   DataCol: Integer;
   Column: TColumn;
   State: TGridDrawState) ;
 var
   grid : TDBGrid;
   row : integer;
 begin
   grid := sender as TDBGrid;
   row := grid.DataSource.DataSet.RecNo;
   if Odd(row) then
     grid.Canvas.Brush.Color := clSilver
   else
     grid.Canvas.Brush.Color := clWhite;

   grid.DefaultDrawColumnCell(Rect, DataCol, Column, State) ;
  end;

end.
